﻿#region Creditos

/* Autor: Edilberto Sánchez Forero	*/
/* Email: esanchezfo@gmail.com		*/
/* Licencia: LGPL, Software Libre	*/
/* País: Colombia, Bogotá			*/

#endregion

#region Librerias

using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;

using Microsoft.Reporting.WebForms;

using ESF.General;
using System.Xml;
using System.IO;

#endregion


namespace ESF.MSReporting
{
	public class ReportParams
	{
		#region Formatos
		
		public enum ExportFormat
		{
			Word,
			Excel,
			Image,
			PDF
		}
		
		#endregion
	
	
		#region Constantes
		
		public const string RESUME_PARAMNAME = "pResumenParametros";
				
		public const string RENDERAS_PARAMNAME = "pRenderAs";
		public const string RENDER_NOTIFYEMAIL = "pRenderNotifyEmail";
		public const string RENDER_PUBLISHFOLDER = "pRenderPublishFolder";
		public const string RENDERTOFILENAME_PARAMNAME = "pRenderToFilename";
		public const string RENDER_DOZIP = "pRenderDoZip";
		public const string RENDER_DOZIPPASSWORD = "pRenderDoZipPassword";
		public const string RENDER_DELETEOLD = "pRenderDeleteOld";
		public const string RENDER_DIRECTLY = "pRenderDirectly";
		public const string ALLOW_PRINT_REPORT = "pAllowPrintReport";
		public const string ALLOW_EXPORT_REPORT = "pAllowExportReport";
		
		#endregion


		#region Not Show Params

		public List<string> HiddenResumeParamNames;

		#endregion
		
		
		#region Miembros
		
		private List<ReportParam> _Params;
		
		#endregion
	
	
		#region Propiedades


		public bool AllowPrintReport = true;


		public bool AllowExportReport = true;

		
		public bool IncludeResumen { set; get; }
		
		
		public ExportFormat? RenderAs { set; get; }
		
		
		public string RenderToFilename { set; get; }


		public bool RenderDirectly { set; get; }


		public string RenderNotifyEmail { set; get; }
		
		
		public List<ReportParameter> ReportingParams
		{
			get
			{
				List<ReportParameter> _ReportingParams;
				
			
				_ReportingParams = new List<ReportParameter> (_Params.Count);
			
				foreach (ReportParam param in _Params)
				{
					if (!TextHelper.IsEmpty (param.Value.ToString ()))
					{
						_ReportingParams.Add (new ReportParameter (param.Name, param.Value.ToString ()));
					}
				}
				

				if (RenderAs != null)
				{
					_ReportingParams.Add (new ReportParameter (RENDERAS_PARAMNAME, RenderAs.ToString ()));
				}


				if (!string.IsNullOrEmpty(RenderToFilename))
				{
					_ReportingParams.Add(new ReportParameter(RENDERTOFILENAME_PARAMNAME, RenderToFilename));
				}


				_ReportingParams.Add (new ReportParameter (RENDER_DIRECTLY, RenderDirectly.ToString ()));


				if (!string.IsNullOrEmpty (RenderNotifyEmail))
				{
					_ReportingParams.Add(new ReportParameter(RENDER_NOTIFYEMAIL, RenderNotifyEmail));
				}


				_ReportingParams.Add(new ReportParameter(ALLOW_EXPORT_REPORT, AllowExportReport.ToString ()));

				_ReportingParams.Add (new ReportParameter (ALLOW_PRINT_REPORT, AllowPrintReport.ToString ()));
			
				
				if (IncludeResumen)
				{
					_ReportingParams.Add (new ReportParameter (RESUME_PARAMNAME, GetParamsResume ()));
				}
				
				return _ReportingParams;
			}
		}

		#endregion
		
		
		#region Constructor
		
		public ReportParams ()
			: this (true) {}
		
		
		public ReportParams (bool pIncludeResumen)
		{
			_Params = new List<ReportParam> ();
			
			IncludeResumen = pIncludeResumen;

			RenderDirectly = true;

			HiddenResumeParamNames = new List<string> ();

			HiddenResumeParamNames.Add (ALLOW_PRINT_REPORT);
			HiddenResumeParamNames.Add (ALLOW_EXPORT_REPORT);
		}
		
		#endregion
		
		
		#region Funciones de Resumen

		public XmlDocument ParamsAsXML
		{
			get
			{
				XmlDocument result;


				if (_Params.Count == 0)
				{
					result = null;
				}
				else
				{
					StringBuilder stringBuilder = new StringBuilder();
					XmlTextWriter xmlTextWriter = new XmlTextWriter(new StringWriter(stringBuilder));
					xmlTextWriter.WriteStartElement("Parametros");
					foreach (ReportParam current in _Params)
					{
						xmlTextWriter.WriteStartElement("Parametro");
						xmlTextWriter.WriteAttributeString("Nombre", current.Name);
						xmlTextWriter.WriteAttributeString("Titulo", current.Title);
						xmlTextWriter.WriteAttributeString("Valor", current.Value.ToString ());
						xmlTextWriter.WriteAttributeString("Descripción", current.Description);
						xmlTextWriter.WriteEndElement();
					}
					xmlTextWriter.WriteEndElement();
					xmlTextWriter.Close();
					XmlDocument xmlDocument = new XmlDocument();
					xmlDocument.LoadXml(stringBuilder.ToString());
					result = xmlDocument;
				}
				return result;
			}
		}


		public string GetParamsResume ()
		{
			StringBuilder resume;
			

			if (DataHelper.IsEmpty (_Params)) { return "Ninguno"; }

			resume = new StringBuilder ();

			foreach (ReportParam param in _Params)
			{
				if (!HiddenResumeParamNames.Exists (i => string.Compare (i, param.Name, true) == 0))
				{
					resume.AppendFormat("{0}: ", param.Title);
				
					if (string.IsNullOrEmpty (param.Description))
					{			
						resume.Append (param.Value);
					}
					else
					{
						resume.Append (param.Description);
					}
				
					resume.Append (" -- ");
				}
			}

			return resume.ToString();

		}
		
		#endregion
		
		
		#region Funciones de Parametros
		
		public void AddInteger(string strTitle, string strName, string strValue)
		{
			AddInteger(strTitle, strName, strValue, strValue);
		}

		/// <summary>
		/// Adiciona un parametro de tipo numerico
		/// </summary>
		public void AddInteger(string strTitle, string strName, string strValue, string strDescripcion)
		{
			if (TextHelper.IsEmpty(strValue)) { return; }

			AddInteger(strTitle, strName, Convert.ToInt32(strValue), strDescripcion);
		}


		/// <summary>
		/// Adiciona un parametro de tipo numerico
		/// </summary>
		public void AddInteger(string strTitle, string strName, int intValue, string strDescripcion)
		{
			AddString(strTitle, strName, intValue.ToString(), strDescripcion);
		}
		
		
		public void AddPositiveInteger (string strTitle, string strName, string pValue)
		{
			AddPositiveInteger (strTitle, strName, TextHelper.GetInt (pValue));
		}


		public void AddPositiveInteger (string strTitle, string strName, int intValue)
		{
			AddPositiveInteger (strTitle, strName, intValue, intValue.ToString ());
		}
		
		
		public void AddPositiveInteger (string strTitle, string strName, int intValue, string strDescripcion)
		{
			if (intValue <= 0) { return; }
			
			AddInteger (strTitle, strName, (int) intValue, strDescripcion);
		}

		#endregion

		
		#region Add Bool

		public void AddBool (string strTitle, string strName, string strValue)
		{
			AddBool (strTitle, strName, strValue, null);
		}
		

		public void AddBool (string strTitle, string strName, string strValue, string pstrDescripcion)
		{
			AddBool (strTitle, strName, strValue, false, pstrDescripcion);
		}
		

		public void AddBool (string strTitle, string strName, string strValue, bool blnFalseIsNull)
		{
			AddBool (strTitle, strName, strValue, blnFalseIsNull, null);
		}


		public void AddBool (string strTitle, string strName, bool blnValue)
		{
			AddBool (strTitle, strName, blnValue, false);
		}


		public void AddBool (string strTitle, string strName, bool blnValue, bool blnFalseIsNull)
		{
			AddBool (strTitle, strName, blnValue, blnFalseIsNull, null);
		}


		public void AddBool (string strTitle, string strName, bool blnValue, string pstrDescripcion)
		{
			AddBool (strTitle, strName, blnValue, false, pstrDescripcion);
		}
		

		public void AddBool (string strTitle, string strName, string strValue, bool blnFalseIsNull, string strDescripcion)
		{
			bool blnValue;


			if (TextHelper.IsEmpty (strValue)) { return; }

			bool.TryParse (strValue, out blnValue);
			
			AddBool (strTitle, strName, blnValue, blnFalseIsNull, strDescripcion);
		}
		

		public void AddBool (string strTitle, string strName, bool blnValue, bool blnFalseIsNull, string strDescripcion)
		{
			if (!blnValue && blnFalseIsNull) { return; }
			
			if (TextHelper.IsEmpty (strDescripcion)) { strDescripcion = (blnValue ? "Sí" : "No"); }

			AddString (strTitle, strName, (blnValue ? "true" : "false"), strDescripcion);
		}

		#endregion


		#region Funciones para Add ID

		public void AddIDs(string strTitle, string strName, List<int> intValuees, List<string> strDescripciones)
		{
			int intI;

			StringBuilder strValue;
			StringBuilder strDescripcion;


			if (intValuees.Count == 0) { return; }

			strValue = new StringBuilder();
			strDescripcion = new StringBuilder();

			for (intI = 1; intI <= intValuees.Count - 1; intI++)
			{
				strValue.AppendFormat(", {0}", intValuees[intI]);
				strDescripcion.AppendFormat(", {0}", strDescripciones[intI]);
			}

			strValue.Insert(0, intValuees[0]);
			strDescripcion.Insert(0, strDescripciones[0]);

			//FIXME: Demasiado largo el request
			//AddString (strTitle, strName, strValue.ToString (), strDescripcion.ToString ());
			AddString(strTitle, strName, strValue.ToString(), string.Empty);
		}


		public void AddID(string strTitle, string strName, string strID, string strDescripcion)
		{
			if (string.IsNullOrEmpty(strID)) { return; }

			AddID(strTitle, strName, Convert.ToInt32(strID), strDescripcion);
		}


		public void AddID(string strTitle, string strName, int intID, string strDescripcion)
		{
			if (intID <= 0) { return; }

			AddString(strTitle, strName, intID.ToString(), strDescripcion);
		}

		#endregion


		#region Funciones para Add String

		public void AddString(string strTitle, string strValue)
		{
			AddString (strTitle, strTitle, strValue);
		}

		public void AddString(string strTitle, string strName, string strValue)
		{
			AddString(strTitle, strName, strValue, strValue);
		}


		public void AddString(string strTitle, string strName, string strValue, string strDescripcion)
		{
			if (TextHelper.IsEmpty (strValue)) { return; }

			_Params.Add(new ReportParam () { Title = strTitle, Name = strName, Value = strValue, Description = strDescripcion });
		}

		#endregion


		#region Funciones para Add Date

		public void AddDate(string strTitle, string strName, string strDate)
		{
			DateTime dtmDate;
			
		
			if (!DateTime.TryParse (strDate.Trim(), out dtmDate)) { return; }

			AddDate(strTitle, strName, dtmDate);
		}


		public void AddDate(string strTitle, string strName, DateTime dtmDate)
		{
			AddDate(strTitle, strName, dtmDate, "yyyy-MM-dd");
		}
		
		
		public void AddStartDate (string pstrTitle, string pstrName, string pstrDate)
		{
			DateTime dtmDate;
			
		
			if (!DateTime.TryParse (pstrDate.Trim(), out dtmDate)) { return; }
		
			AddStartDate (pstrTitle, pstrName, dtmDate);
		}
		
		
		public void AddStartDate (string pstrTitle, string pstrName, DateTime pdtmDate)
		{
			pdtmDate = new DateTime (pdtmDate.Year, pdtmDate.Month, pdtmDate.Day, 0, 0, 0);

			AddDate (pstrTitle, pstrName, pdtmDate, "yyyy-MM-dd HH:mm:ss");
		}


		public void AddEndDate (string pstrTitle, string pstrName, string pstrDate)
		{
			DateTime dtmDate;


			if (!DateTime.TryParse (pstrDate.Trim (), out dtmDate)) { return; }

			AddEndDate (pstrTitle, pstrName, dtmDate);
		}


		public void AddEndDate (string pstrTitle, string pstrName, DateTime pdtmDate)
		{
			pdtmDate = new DateTime (pdtmDate.Year, pdtmDate.Month, pdtmDate.Day, 23, 59, 59);

			AddDate (pstrTitle, pstrName, pdtmDate, "yyyy-MM-dd HH:mm:ss");
		}


		private void AddDate(string pstrTitle, string strName, DateTime dtmDate, string strFormato)
		{
			if (dtmDate.Year == DateTime.MinValue.Year || dtmDate.Year == DateTime.MaxValue.Year) { return; }

			AddString(pstrTitle, strName, dtmDate.ToString(strFormato), dtmDate.ToString(strFormato));
		}
		
		
		public void AddDateRange (string pStartTitle, string pStartName, string pStartYear, string pStartMonth,
			string pEndTitle, string pEndName, string pEndYear, string pEndMonth)
		{
			int startYear = DateTime.MinValue.Year;
			int startMonth = 0;
			
			int endYear = DateTime.MaxValue.Year;
			int endMonth = 0;
			
			
			if (string.IsNullOrEmpty (pStartYear) || !int.TryParse (pStartYear, out startYear)) { throw new GenericInfoException (pStartTitle + ": año incorrecto"); }
			
			if (string.IsNullOrEmpty (pStartMonth) || !int.TryParse (pStartMonth, out startMonth)) { throw new GenericInfoException (pStartTitle + ": mes incorrecto");; }
			
			if (string.IsNullOrEmpty (pEndYear) || !int.TryParse (pEndYear, out endYear)) { throw new GenericInfoException (pEndTitle + ": año incorrecto"); }
			
			if (string.IsNullOrEmpty (pEndMonth) || !int.TryParse (pEndMonth, out endMonth)) { throw new GenericInfoException (pEndTitle + ": mes incorrecto");; }
			
			AddDateRange (pStartTitle, pStartName, startYear, startMonth, pEndTitle, pEndName, endYear, endMonth);
		}
		
		
		public void AddDateRange (string pStartTitle, string pStartName, int pStartYear, int pStartMonth,
			string pEndTitle, string pEndName, int pEndYear, int pEndMonth)
		{
			DateTime startDate;
			DateTime endDate;
			
			
			startDate = new DateTime (pStartYear, pStartMonth, 1, 0, 0, 0);
			
			if (pEndMonth == 12)
			{
				if (pEndYear == DateTime.MaxValue.Year) { endDate = DateTime.MaxValue; }
				else { endDate = new DateTime (pEndYear + 1, 1, 1).AddDays (-1); }
				
				AddDateRange (pStartTitle, pStartName, startDate, 
					pEndTitle, pEndName, endDate);  
			}
			else
			{
				if (pEndYear == DateTime.MaxValue.Year) { endDate = DateTime.MaxValue; }
				else { endDate = new DateTime (pEndYear, pEndMonth + 1, 1).AddDays (-1); }
			
				AddDateRange (pStartTitle, pStartName, startDate, 
					pEndTitle, pEndName, endDate);  
			}
		}
		
		
		public void AddDateRange (string pStartTitle, string pStartName, string pStartDate, string pEndTitle, string pEndName, string pEndDate)
		{
			AddDateRange (pStartTitle, pStartName, pStartDate, pEndTitle, pEndName, pEndDate, "yyyy-MM-dd");
		}
		
		
		public void AddDateRange (string pStartTitle, string pStartName, string pStartDate, string pEndTitle, string pEndName, string pEndDate, string pDateFormat)
		{
			DateTime startDate = DateTime.MinValue;
			DateTime endDate = DateTime.MaxValue;
			
			
			if (!string.IsNullOrEmpty (pStartDate) && !DateTime.TryParseExact (pStartDate, pDateFormat, CultureInfo.InvariantCulture,DateTimeStyles.None, out startDate))
			{
				return;
			}
			
			if (!string.IsNullOrEmpty (pEndDate) && !DateTime.TryParseExact (pEndDate, pDateFormat, CultureInfo.InvariantCulture,DateTimeStyles.None, out endDate))
			{
				return;
			}
			
			AddDateRange (pStartTitle, pStartName, startDate, pEndTitle, pEndName, endDate);
		}
		
		
		public void AddDateRange (string pStartTitle, string pStartName, DateTime pStartDate, string pEndTitle, string pEndName, DateTime pEndDate)
		{
			Validate.VerifyDateRange (pStartTitle, pStartDate, pEndTitle, pEndDate);
			
			AddStartDate (pStartTitle, pStartName, pStartDate);
			AddEndDate (pEndTitle, pEndName, pEndDate);
		}
		
		
		public void AddYearDateRange (string pStartTitle, string pStartName, string pStartYear,
			string pEndTitle, string pEndName, string pEndYear)
		{
			AddDateRange (pStartTitle, pStartYear, "1", pEndTitle, pEndYear, "12"); 
		}
		
		
		public void AddYearDateRange (string pStartTitle, string pStartName, int pStartYear,
			string pEndTitle, string pEndName, int pEndYear)
		{
			AddDateRange (pStartTitle, pStartName, pStartYear, 1, pEndTitle, pEndName, pEndYear, 12);
		}

		#endregion


		#region ToString

		public override string ToString()
		{
			return GetParamsResume ();
		}

		#endregion
	}
}
